package com.example.demo.lock;

import java.util.Calendar;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;

@SuppressWarnings("AlibabaAvoidManuallyCreateThread")
public class Demo{
    //同步资源
    private String name;
    private ReentrantLock lock = new ReentrantLock();

    //悲观锁实现一
    public synchronized void updateName(String name, Integer threadNum) throws InterruptedException {
        //do something about name
        System.out.println(threadNum + "is doing something at " + Calendar.getInstance().getTimeInMillis());
        this.name = name;
        //为了演示效果故休眠 1s
        Thread.sleep(1000);
    }

    //悲观锁实现二
    public void setName(String name, Integer threadNum) throws InterruptedException {
        //阻塞直到获取到锁
        lock.lock();
        try{
            //do something about name
            System.out.println(threadNum + " is doing something at " + Calendar.getInstance().getTimeInMillis());
            this.name = name;
            //为了演示效果故休眠 1s
            Thread.sleep(1000);
        }finally{
            lock.unlock();
        }
    }

    public void setNameWithNoLock(String name, Integer threadNum)throws InterruptedException {
        //do something about name
        System.out.println(threadNum + " is doing something at " + Calendar.getInstance().getTimeInMillis());
        this.name = name;
        //为了演示效果故休眠 1s
        Thread.sleep(1000);
    }

    public static void main(String[] args) throws InterruptedException {
        Demo demo = new Demo();

        //悲观锁
        final CountDownLatch latch = new CountDownLatch(10);
        System.out.println("悲观锁输出结果，请注意看输出的时间戳：");
        for(int i=0;i<10;i++){
            final int num = i;
            new Thread(() -> {
                try {
                    demo.setName("乌鸦"+num,num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
            }).start();
        }
        //主要是为了 hold 主线程，让 10 个线程跑完
        latch.await();

        //无锁
        final CountDownLatch latch2 = new CountDownLatch(10);
        System.out.println("乐观锁输出结果，请注意看输出的时间戳：");
        for(int i=0;i<10;i++){
            final int num = i;
            new Thread(() -> {
                try {
                    demo.setNameWithNoLock("乌鸦"+num,num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch2.countDown();
            }).start();
        }
        //主要是为了 hold 主线程，让 10 个线程跑完
        latch2.await();
    }
}
